/*
 * ============================================================================
 *
 *       Filename:  14-1.c
 *
 *    Description:  my media server
 *
 *        Version:  1.0
 *        Created:  2017年03月27日 22时07分12秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  yangkun (yk)
 *          Email:  xyyangkun@163.com
 *        Company:  yangkun.com
 *
 * ============================================================================
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h> 
#include <sys/time.h>

#ifdef MODULE
#undef MODULE
#endif 
#define MODULE "MEDIASRV"
#include "dbg.h"

#include "my_netio.h"
#include "media_api.h"
#include "getnal.h"

static media_source_t media;
#define BUFFER_SIZE 400*1024
static unsigned char frame_buffer[BUFFER_SIZE];	//帧缓冲区大小400k

#define MAXLINE 800000
/*****************************************************************************
 * brief main function
 *****************************************************************************/
int main ( int argc, char *argv[] )
{
	_dbg_init();
	dbg("test\n");
	struct sockaddr_in cliaddr;
	socklen_t cliaddr_len;
	int listenfd, connfd;
	int ret;
	char buf[MAXLINE];
	char str[20];

	// spspps的大小
	int ofs;

	// frame point size
	unsigned char *pfb;
	unsigned int fbsize;

	//池子
	char name[256]="enc0";	//池子的名字

	//其它数据
	int		seq=-1;                 ///<媒体数据序号
	int 	flag;

	//初始化数据
	memset(&media ,0, sizeof(media_source_t));
	media.dev_stat= -1; //表示没有连接
	printf("d1\n");

	ret=connect_media_read(&media ,0x30000, name, MSHMPOOL_LOCAL_USR);
	if(ret<0)
	{
		printf("error in connect media read and exit\n");
		goto error;
	}
	//debug
	printf("here1\n");
#if 1
	ret=move_media_place(&media, -20);
	if(ret<0)
	{
		printf(" cat move media place and exit\n");
		goto error;
	}
#endif
	printf("the remain:%d\n",ret);
	printf("here2\n");

	// get sps/pps from the media pool
	while(1)
	{
		// usleep(33000);		//30帧
		//debug
		ret=read_media_remain(&media);
		if(ret<0)
		{
			printf("get media remain error\n");
			goto error;
		}
		printf("the remain:%d\n",ret);

		//读取帧，返回值为帧大小 但是kframe是什么呢？
		//　难道flag 就是是不是I帧的那项？
		memset(frame_buffer, 0, BUFFER_SIZE);
		seq=-1;flag=-1;
		ret=read_media_resource(&media,frame_buffer, BUFFER_SIZE, &seq, &flag);
		if(ret<0)
		{
			printf("error in read media resource\n");
			goto error;
		}
#if 0
		// if (flag == 1)
		{
			printf("is keyframe:%#x %#x %#x %#x %#x %#x %#x %#x %#x\n", \
					frame_buffer[0], frame_buffer[1], frame_buffer[2], \
					frame_buffer[3], frame_buffer[4],frame_buffer[5], \
					frame_buffer[6], frame_buffer[7],frame_buffer[8]);
		}
#endif
		if (flag != 0)
		{
			printf("not iFRame continue\n");
			continue;
		}
		else
		{
			printf("is iFrame !!!\n");
		}
		pfb = frame_buffer;
		fbsize = ret;
		//debug
		printf("the frame size is %d,seq=%d,flag=%d\n",ret,seq,flag);

		ret = get_spspps(pfb, fbsize, (unsigned int *)&ofs);
		if (ret != 0)
		{
			printf("this is not I frame:%d\n", ret);
			continue;
		}
		else
		{
			/// 找到sps/pps
			printf("=============> found sps/pps, size:%d\n", ofs);
			break;
		}

		if (flag == 1)
		{
			break;
		}
	}


	// listenfd = my_create_tcp_server("192.168.109.128", 8000);
	listenfd = my_create_tcp_server("0.0.0.0", 8000);
	if (listenfd < 0)
	{
		dbg("ERROR in my create tcp serer!\n");
		exit(EXIT_FAILURE);
	}

	cliaddr_len = sizeof(cliaddr);

	connfd = my_accept(listenfd, &cliaddr, &cliaddr_len);
	if (connfd < 0)
	{
		dbg("ERROR in my accpet\n");
		exit(EXIT_FAILURE);
	}
	#define headlen 5
	// 1. 获取media name
	{
		ret = my_read(connfd, buf, headlen);
		if (ret <= 0)
		{
			dbg("ERROR in read:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}
		#pragma pack(1)
		struct media_name
		{
			unsigned char cmd_id;
			unsigned int  len;
			char name[];
		};
		struct media_name *p = (struct media_name *)buf;
		p->cmd_id = 0x1e;
		p->len = 10;
		dbg("media name ret:%d   len:%u\n", ret, p->len);
		///printf("%#x %#x %#X %#X %#x\n", buf[0], buf[1], buf[2], buf[3], buf[4]);
		ret = my_read(connfd, buf+headlen, p->len-headlen);
		if (ret <= 0)
		{
			dbg("ERROR in read:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}
		dbg("media name:ret=%d:%s\n", ret, p->name);
		printf("media name:%s\n", p->name);
	}

	/// have audio?
	{
		ret = my_read(connfd, buf, headlen);
		if (ret <= 0)
		{
			dbg("ERROR in read:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}
		#pragma pack(1)
		struct media_name
		{
			unsigned char cmd_id;
			unsigned int  len;
			unsigned char have_audio;
		};
		struct media_name *p = (struct media_name *)buf;
		dbg("media name ret:%d   len:%u\n", ret, p->len);

		p->len = 6;
		p->have_audio = 0;
		ret = my_write(connfd, buf, p->len);
		if (ret <= 0)
		{
			dbg("ERROR in read:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}

	}

	/// sps/pps
	// 发送h264文件头
	{
#pragma pack(1)
		struct media_content
		{
			unsigned char cmd_id;
			unsigned int  len;
			unsigned char buf[];
		};

		ret = my_read(connfd, buf, headlen);
		if (ret <= 0)
		{
			dbg("ERROR in read:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}
		struct media_content *p = (struct media_content *)buf;
		dbg("media content id:%#x   len:%u\n", p->cmd_id, p->len);
		
		/// 置0 buf
		memset(p->buf, 0, sizeof(buf)-sizeof(struct media_content));
		memcpy(&p->buf, frame_buffer, ofs);
		p->len = ofs;
		dbg("write len:%d\n", p->len);
		ret = my_write(connfd, buf, p->len);
		if (ret <= 0)
		{
			dbg("ERROR in write:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}

	}

	// 接收点播命令
	{
#pragma pack(1)
		struct media_content
		{
			unsigned char cmd_id;
			unsigned int  len;
			unsigned char buf[];
		};

		ret = my_read(connfd, buf, headlen);
		if (ret <= 0)
		{
			dbg("ERROR in read:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}
		struct media_content *p = (struct media_content *)buf;
		dbg("media content id:%#x   len:%u\n", p->cmd_id, p->len);

		ret = my_read(connfd, buf, headlen);
		if (ret <= 0)
		{
			dbg("ERROR in read:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}
		dbg("media content id:%#x   len:%u\n", p->cmd_id, p->len);
		
	}

	/// exit(0);

	struct timeval _time;
#pragma pack(1)
	struct media_send
	{
		unsigned char cmd_id;
		unsigned int  len;
		unsigned char type;
		long long timemark;
		char buf[];
	};


	//// 循环发送264文件
	while(1)
	{
		//读取帧，返回值为帧大小 但是kframe是什么呢？
		//　难道flag 就是是不是I帧的那项？
		memset(frame_buffer, 0, BUFFER_SIZE);
		seq=-1;flag=-1;
		ret=read_media_resource(&media,frame_buffer, BUFFER_SIZE, &seq, &flag);
		if(ret<0)
		{
			printf("error in read media resource\n");
			goto error;
		}
		pfb = frame_buffer;
		fbsize = ret;

		//debug
		printf("the frame size is %d,seq=%d,flag=%d\n",ret,seq,flag);

		struct media_send *p = (struct media_send *)buf;
		dbg("media content id:%#x   len:%u\n", p->cmd_id, p->len);
		
		/// 置0 buf
		memset(p->buf, 0, sizeof(buf)-sizeof(struct media_send));
		/// 获取时间
		gettimeofday(&_time, NULL);
		p->cmd_id =  0x2;
		p->timemark = _time.tv_sec*1000000+_time.tv_usec;
		/// 类型
		p->type = 0x33;


		memcpy(&p->buf, pfb, fbsize);
		p->len = fbsize;

		 dbg("%#X %#X %#X %#X %#X\n", 
				*(p->buf),
				*(p->buf+1),
				*(p->buf+2),
				*(p->buf+3),
				*(p->buf+4));
		ret = my_write(connfd, buf, p->len);
		if (ret <= 0)
		{
			 dbg("ERROR in read:%s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}

	}






	// dbg("over\n");
	close(connfd);

	return EXIT_SUCCESS;
error:
	return -1;
}				/* ----------  end of function main  ---------- */

/*****************************************************************************
 * brief 
 *****************************************************************************/
